package com.excel.manager.excel;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import com.excel.manager.annotation.Columns;
import com.excel.manager.utils.Utils;

/**
 * @author ravi
 * */
public class ExcelToBean<T> {

    private Map<Object, Integer> excelHeaderMap;
    private List<String> annotatedHeaders = new ArrayList<String>();
    private Map<String, Field> fieldMapping = new HashMap<String, Field>();

    public Set<T> mapExcelToBean(int headerRow, Class<T> clazz, Sheet sheet) throws ClassNotFoundException, InstantiationException,
            IllegalAccessException {

        excelHeaderMap = Utilities.createHeaderMap(sheet, headerRow);
        Field[] fields = clazz.getFields();

        for (Field field : fields) {
            Columns column = field.getAnnotation(Columns.class);
            if (column == null || column.value() == null || column.value().trim().equals("")) {
                continue;
            }
            annotatedHeaders.add(column.value());
            fieldMapping.put(column.value(), field);
        }

        List<T> listBean = new ArrayList<T>();
        for (Row row : sheet) {
            if (row.getRowNum() <= headerRow) {
                continue;
            }
            listBean.add(craeateProductBean(row, clazz));
        }
        return new HashSet<T>(listBean);
    }

    private T craeateProductBean(Row row, Class<T> clazz) throws InstantiationException, IllegalAccessException {
        final T objInstance = clazz.newInstance();

        if (row == null) {
            return null;
        }

        for (Map.Entry<Object, Integer> entry : excelHeaderMap.entrySet()) {

            if (!annotatedHeaders.contains(entry.getKey())) {
                continue;
            }

            Cell cell = row.getCell(entry.getValue());
            Field field = fieldMapping.get(entry.getKey());

            if (cell == null) {
                continue;
            }

            Object cellValue = Utilities.getCellValue(cell);
            if (cellValue == null) {
                continue;
            }

            if (cellValue instanceof Double) {
                if (Utils.isEmptyOrNull(cellValue)) {
                    cellValue = 0;
                }
                field.set(objInstance, (Double) cellValue);

            } else if (cellValue instanceof String) {
                try {
                    if (!Utils.isEmptyOrNull(cellValue)) {
                        field.set(objInstance, (String) cellValue);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new IllegalArgumentException();
                }

            } else if (cellValue instanceof Date) {
                if (!Utils.isEmptyOrNull(cellValue)) {
                    field.set(objInstance, (Date) cellValue);
                }

            } else if (cellValue instanceof Boolean) {
                if (!Utils.isEmptyOrNull(cellValue)) {
                    cellValue = false;
                }
                field.set(objInstance, (Boolean) cellValue);
            }
        }
        return objInstance;
    }
}
